/*
 * Copyright (c) 2015 DHC Corporation.
 */

package cn.com.dhc.danlu.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * 多行TextView文字后显示...的TextView
 *
 * @author MuWei
 * @version 1.00 2015/02/03 新建
 */
public class EllipsizingTextView extends TextView {

    private static final String ELLIPSIS = "...";
    private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<> ();
    private Handler mHandler = new Handler ();
    private boolean mIsEllipsized = false;
    private boolean isStale = false;
    private boolean programmaticChange = false;
    private String fullText = null;
    private int maxLines = -1;
    private float lineSpacingMultiplier = 1.0f;
    private float lineAdditionalVerticalPadding = 0.0f;
    public EllipsizingTextView (Context context) {
        super (context);
    }

    public EllipsizingTextView (Context context, AttributeSet attrs) {
        super (context, attrs);
    }

    public EllipsizingTextView (Context context, AttributeSet attrs, int defStyle) {
        super (context, attrs, defStyle);
    }

    public void addEllipsizeListener (EllipsizeListener listener) {
        if (listener == null) {
            throw new NullPointerException ();
        }
        ellipsizeListeners.add (listener);
    }

    public void removeEllipsizeListener (EllipsizeListener listener) {
        ellipsizeListeners.remove (listener);
    }

    public boolean isEllipsized () {
        return mIsEllipsized;
    }

    /**
     * 文本设定
     */
    private void resetText () {
        boolean isEnter = false;
        int maxLinesTemp = getMaxLines ();
        String workingText = fullText;
        boolean ellipsized = false;
        if (maxLinesTemp != -1) {
            Layout layout = createWorkingLayout (workingText);
            if (layout.getLineCount () > maxLinesTemp) {
                workingText = fullText.substring (0,
                        layout.getLineEnd (maxLinesTemp - 1));

                if (workingText.charAt (workingText.length () - 1) == '\n') {
                    isEnter = true;
                }

                workingText = workingText.trim ();

                while (createWorkingLayout (workingText + ELLIPSIS)
                        .getLineCount () > maxLinesTemp) {
                    // int lastSpace = workingText.lastIndexOf(' ');
                    // if (lastSpace == -1) {
                    // break;
                    // }
                    workingText = workingText.substring (0,
                            workingText.length () - 1);
                }
                if (maxLines == 1) {
                    workingText = workingText + ELLIPSIS;
                } else {
                    if (isEnter) {
                        if (createWorkingLayout (workingText + ELLIPSIS)
                                .getLineCount () > maxLinesTemp) {
                            workingText = workingText.substring (0,
                                    workingText.length () - 1)
                                    + ELLIPSIS;
                        } else {
                            workingText = workingText + ELLIPSIS;
                        }
                    } else {
                        workingText = workingText.substring (0,
                                workingText.length () - 1)
                                + ELLIPSIS;
                    }
                }
                ellipsized = true;
            }
        }
        if (!workingText.equals (getText ())) {
            programmaticChange = true;
            try {
                setText (workingText);
            } finally {
                programmaticChange = false;
            }
        }
        isStale = false;
        if (ellipsized != mIsEllipsized) {
            mIsEllipsized = ellipsized;
            for (EllipsizeListener listener : ellipsizeListeners) {
                listener.ellipsizeStateChanged (ellipsized);
            }
        }
    }

    private Layout createWorkingLayout (String workingText) {
        return new StaticLayout (workingText, getPaint (), getWidth ()
                - getPaddingLeft () - getPaddingRight (), Alignment.ALIGN_NORMAL,
                lineSpacingMultiplier, lineAdditionalVerticalPadding, false);
    }    @Override
    public void setMaxLines (int maxLines) {
        super.setMaxLines (maxLines);
        this.maxLines = maxLines;
        isStale = true;
    }

    public interface EllipsizeListener {
        void ellipsizeStateChanged (boolean ellipsized);
    }    public int getMaxLines () {
        return maxLines;
    }

    @Override
    public void setLineSpacing (float add, float mult) {
        this.lineAdditionalVerticalPadding = add;
        this.lineSpacingMultiplier = mult;
        super.setLineSpacing (add, mult);
    }

    @Override
    protected void onTextChanged (CharSequence text, int start, int before,
                                  int after) {
        super.onTextChanged (text, start, before, after);
        if (!programmaticChange) {
            fullText = text.toString ();
            isStale = true;
        }
    }

    @SuppressLint ("DrawAllocation")
    @Override
    protected void onDraw (Canvas canvas) {

        // 为防止2.x系统UI主线程栈溢出问题
        try {
            if (isStale) {
                super.setEllipsize (null);
                resetText ();
            }
            super.onDraw (canvas);
        } catch (StackOverflowError e) {
            mHandler.postDelayed (new Runnable () {
                public void run () {
                    invalidate ();
                }
            }, 1);
        }
    }





    @Override
    public void setEllipsize (TruncateAt where) {
        // Ellipsize settings are not respected
    }
}
